package net.pulseproject.commons.misc.collection;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class EnablerCollectionImpl<V, E extends Enableable> implements EnablerCollection<V, E> {
	
	private static final Log LOG = LogFactory.getLog(EnablerCollectionImpl.class);
	
	private final Map<V, E> enableablesByValue = new HashMap<V, E>();
	
	
	public EnablerCollectionImpl(final Map<V, E> originalMap) {
		if(originalMap == null) { throw new IllegalArgumentException("originalMap == null"); }
		if(originalMap.isEmpty()) { throw new IllegalArgumentException("originalMap is empty"); }
		
		this.enableablesByValue.putAll(originalMap);
	}
	
	@Override
	public final void setEnabledFor(final V value, final boolean enabled) {
		LOG.trace("setEnabledFor(value=" + value + ", enabled=" + enabled + ")");
		if(value == null) { throw new IllegalArgumentException("value == null"); }
		
		final E entry = this.enableablesByValue.get(value);
		if(entry == null) {
			throw this.entryNullException(value);
		}
		
		entry.setEnabled(enabled);
	}

	@Override
	public final boolean isEnabledFor(final V value) {
		LOG.trace("isEnabledFor(value=" + value + ")");
		if(value == null) { throw new IllegalArgumentException("value == null"); }
		
		final E entry = this.enableablesByValue.get(value);
		if(entry == null) {
			throw this.entryNullException(value);
		}
		
		return entry.isEnabled();
	}
	
	private RuntimeException entryNullException(final V value) {
		return new RuntimeException("Could not find entry for value [" + value + "]! " +
				"Available values: " + Arrays.toString(this.enableablesByValue.keySet().toArray()));
	}

	@Override
	public final void setAllDisabledExcept(final V singleEnabledValue) {
		LOG.info("setAllDisabledExcept(singleEnabledValue=" + singleEnabledValue + ")");
		if(singleEnabledValue == null) { throw new IllegalArgumentException("singleEnabledValue == null"); }
		
		for (final Entry<V, E> entry : this.enableablesByValue.entrySet()) {
			final V v = entry.getKey();
			final E e = entry.getValue();
			e.setEnabled(v.equals(singleEnabledValue));
		}
	}

	@Override
	public final void setAllEnabled() {
		LOG.info("setAllEnabled()");
		
		for (final E e : this.enableablesByValue.values()) {
			e.setEnabled(true);
		}
	}
	
}
